package com.qianhui.orderapi;

import com.qianhui.common.CM;
import com.qianhui.common.GlobalConfig;
import com.qianhui.common.IStatus;
import com.qianhui.dao.GoodsHistoryDAO;
import com.qianhui.dao.OrderDAO;
import com.qianhui.dao.OrderDeclarationDAO;
import com.qianhui.dao.OrderGoodsDAO;
import com.qianhui.orderapi.haiguan.AESMessageSigner;
import com.qianhui.orderapi.tenpay.MchCustomQueryResponse;
import com.qianhui.pojo.GoodsHistory;
import com.qianhui.pojo.Order;
import com.qianhui.pojo.OrderDeclaration;
import com.qianhui.pojo.OrderGoods;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import weixin.popular.util.SignatureUtil;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

public class ODAPI
{

    /**
     * 执行财付通申请
     *
     * @param orderId
     */
    public static void do_tenpay_send(String orderId)
    {

        OrderDeclarationDAO orderDeclarationDAO = new OrderDeclarationDAO();
        OrderDAO orderDAO = new OrderDAO();
        Order order = orderDAO.findById(orderId);
        if (order == null)
        {
            return;
        }

        Map<String, String> map = new HashMap<String, String>();
        // 签名类型，取值：MD5、RSA，默认：MD5
        map.put("sign_type", "MD5");
        // 版本号，默认为1.0
        map.put("service_version", "1.0");
        // 字符编码,取值：GBK、UTF-8，默认：GBK。
        map.put("input_charset", "UTF-8");
        // 多密钥支持的密钥序号，默认1
        map.put("sign_key_index", "1");
        // 商户号
        map.put("partner", GlobalConfig.mch_id);
        // 商户系统内部的订单号
        map.put("out_trade_no", order.getOrderId());
        // 海关 (1广州)
        map.put("customs", "1");
        // 商户在海关登记的备案号，customs非0，此参数必填
        map.put("mch_customs_no", GlobalConfig.mch_customs_no);
        // 证件类型,暂只支持1身份证
        map.put("cert_type", "1");
        // 证件号码
        map.put("cert_id", order.getOrderBuyerPeopleId());
        // 姓名
        map.put("name", order.getOrderBuyerRealName());
        // 业务类型(1 保税进口 2 直邮进口)
        map.put("action_type", "1");

        String sign = SignatureUtil.generateSign(map, GlobalConfig.API_KEY);

        // 签名
        map.put("sign", sign);

        CloseableHttpClient httpclient = HttpClients.custom().build();
        // http://mch.tenpay.com/cgi-bin/mch_custom_declare.cgi
        // http://mch.tenpay.com/cgi-bin/mch_custom_query.cgi
        HttpPost httpPost = new HttpPost("http://api.mch.tenpay.com/cgi-bin/mch_custom_declare.cgi");
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        for (Map.Entry<String, String> entry : map.entrySet())
        {
            // 建立一个NameValuePair数组，用于存储欲传送的参数
            params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }

        System.out.println(CM.getTimeStrNow() + "执行财付通申请代码:" + params.toString());
        // 添加参数
        httpPost.setEntity(new UrlEncodedFormEntity(params, Charset.forName("UTF-8")));

        try
        {
            CloseableHttpResponse response = httpclient.execute(httpPost);
            try
            {
                HttpEntity entity = response.getEntity();
                String responseBody = EntityUtils.toString(entity, "UTF-8");

                System.out.println(CM.getTimeStrNow() + "执行财付通申请代码获得响应:" + responseBody);

                // 用对象解析
                try
                {
                    JAXBContext context = JAXBContext.newInstance(MchCustomQueryResponse.class);
                    Unmarshaller unmarshaller = context.createUnmarshaller();
                    MchCustomQueryResponse root = (MchCustomQueryResponse) unmarshaller.unmarshal(new StringReader(responseBody));
                    System.out.println(root.toString());
                    System.out.println(root.getRetcode() + "," + root.getRetmsg());
                    if (CM.validIsEmptyWithTrim(root.getRetcode()) == false && root.getRetcode().equals("0"))
                    {
                        OrderDeclaration orderDeclarationFromDB = orderDeclarationDAO.findByOrderId(orderId);
                        if (orderDeclarationFromDB != null)
                        {
                            orderDeclarationFromDB.setTenpayStatus(IStatus.ORDER_DECLARATION_STATUS_HAVE_EXECUTED);
                            orderDeclarationFromDB.setTenpayStartTime(new Timestamp(Calendar.getInstance().getTimeInMillis()));
                            orderDeclarationDAO.save(orderDeclarationFromDB);
                        }
                    }
                } catch (JAXBException e)
                {
                    e.printStackTrace();
                }
            } finally
            {
                response.close();
            }
        } catch (Exception e)
        {
            e.printStackTrace();
        } finally
        {
            try
            {
                httpclient.close();
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }

    /**
     * 执行海关申请取消
     *
     * @param orderId
     */
    public static boolean do_haiguan_cancel(String orderId)
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        SimpleDateFormat sdf_standard = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        OrderDeclarationDAO orderDeclarationDAO = new OrderDeclarationDAO();
        OrderDAO orderDAO = new OrderDAO();
        OrderGoodsDAO orderGoodsDAO = new OrderGoodsDAO();
        GoodsHistoryDAO goodsHistoryDAO = new GoodsHistoryDAO();

        OrderDeclaration odTemp = orderDeclarationDAO.findByOrderId(orderId);
        if (odTemp == null)
        {
            return false;
        }

        if (odTemp.getZhijianStatus().equals(IStatus.ORDER_DECLARATION_STATUS_EXECUTE_SUCCESS))
        {
            // 生成订单报文
            String file_name = "880020" + sdf.format(Calendar.getInstance().getTime()) + String.format("%04d", 1);
            try
            {
                Order orderFromDB = orderDAO.findById(odTemp.getOrderId());
                if (orderFromDB == null)
                {
                    return false;
                }
                List<OrderGoods> orderGoodsList = orderGoodsDAO.findByOrderId(odTemp.getOrderId());
                if (orderGoodsList == null || orderGoodsList.size() == 0)
                {
                    return false;
                }

                List<com.qianhui.orderapi.haiguan.EOrderGood> eOrderGoodList = new ArrayList<com.qianhui.orderapi.haiguan.EOrderGood>();

                BigDecimal orderTotalMoney = new BigDecimal(0);
                for (int ogIndex = 0; ogIndex < orderGoodsList.size(); ogIndex++)
                {
                    OrderGoods orderGoodsTemp = orderGoodsList.get(ogIndex);
                    GoodsHistory ghTemp = goodsHistoryDAO.findByGoodsIdAndGoodsUpdateTime(orderGoodsTemp.getGoodsId(), orderGoodsTemp.getGoodsUpdateTime());

                    // 创建对象

                    com.qianhui.orderapi.haiguan.EOrderGood eOrderGood = new com.qianhui.orderapi.haiguan.EOrderGood(String.valueOf(ogIndex + 1), "", "IE151014782853", "深圳市西普茗茶进出口有限公司广州分公司", ghTemp.getGoodsCustomsListNo() == null ? "" : ghTemp.getGoodsCustomsListNo(), String.valueOf(ghTemp.getGoodsPrice()), "011", String.valueOf(orderGoodsTemp.getGoodsNumber()), String.valueOf(ghTemp.getGoodsPrice() * orderGoodsTemp.getGoodsNumber()), "");

                    eOrderGoodList.add(eOrderGood);
                    orderTotalMoney = orderTotalMoney.add(new BigDecimal(ghTemp.getGoodsPrice() * orderGoodsTemp.getGoodsNumber()));
                }

                com.qianhui.orderapi.haiguan.EOrder eOrder = new com.qianhui.orderapi.haiguan.EOrder(orderFromDB.getOrderId(), "I", "C", "IE151014782853", "深圳市西普茗茶进出口有限公司广州分公司", "", "", "", "", String.valueOf(orderTotalMoney.doubleValue()), "142", String.valueOf(orderFromDB.getOrderFreight() == null ? 0 : orderFromDB.getOrderFreight()), "142", String.valueOf(orderFromDB.getOrderActualTax() == null ? 0 : orderFromDB.getOrderActualTax()), "142", "", sdf_standard.format(orderFromDB.getOrderPayTime()));

                com.qianhui.orderapi.haiguan.EOrderGoods eOrderGoods = new com.qianhui.orderapi.haiguan.EOrderGoods(eOrderGoodList);
                com.qianhui.orderapi.haiguan.Declaration declaration = new com.qianhui.orderapi.haiguan.Declaration(eOrder, eOrderGoods);

                com.qianhui.orderapi.haiguan.Head head = new com.qianhui.orderapi.haiguan.Head(file_name, "880020", "IE151014782853", sdf_standard.format(Calendar.getInstance().getTime()), "1.0");

                com.qianhui.orderapi.haiguan.Manifest manifest = new com.qianhui.orderapi.haiguan.Manifest(head, declaration);

                // 生成xml
                JAXBContext context = JAXBContext.newInstance(com.qianhui.orderapi.haiguan.Manifest.class);
                Marshaller marshaller = context.createMarshaller();

                File file = new File(GlobalConfig.file_hai_guan_path_upload + file_name + ".xml");
                if (file.exists() == false)
                {
                    CM.createFileWithDirs(GlobalConfig.file_hai_guan_path_upload + file_name + ".xml");
                }

                FileOutputStream fos = new FileOutputStream(file);
                marshaller.marshal(manifest, fos);
                fos.flush();
                fos.close();

                BufferedReader reader = null;
                StringBuilder sb = new StringBuilder();
                try
                {
                    reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
                    String tempString = null;
                    int line = 1;
                    // 一次读入一行，直到读入null为文件结束
                    while ((tempString = reader.readLine()) != null)
                    {
                        sb.append(tempString);
                        line++;
                    }
                    reader.close();
                } catch (IOException e)
                {
                    e.printStackTrace();
                } finally
                {
                    if (reader != null)
                    {
                        try
                        {
                            reader.close();
                        } catch (IOException e1)
                        {
                        }
                    }
                }
                String xmlStr = sb.toString();
                System.out.println("取消海关订单申报:" + xmlStr);

                AESMessageSigner aesMessageSigner = new AESMessageSigner();
                String xmlAfterEncrypt = aesMessageSigner.encrypt(xmlStr);
                FileOutputStream fos_2 = new FileOutputStream(file);
                fos_2.write(xmlAfterEncrypt.getBytes("UTF-8"));
                fos_2.flush();
                fos_2.close();
            } catch (JAXBException | IOException e)
            {
                e.printStackTrace();
            }

            // FTP上传文件
            try
            {
                FileInputStream in = new FileInputStream(new File(GlobalConfig.file_hai_guan_path_upload + file_name + ".xml"));
                boolean flag = CM.uploadFile("210.21.48.7", 2312, "SZQHGZ", "SZQHGZ", "/UPLOAD", file_name + ".xml", in);

                if (flag == true)
                {
                    odTemp.setHaiguanCode(null);
                    odTemp.setHaiguanStatus(IStatus.ORDER_DECLARATION_STATUS_CANCELING);
                    odTemp.setHaiguanInfo("取消海关申请中,取消成功将重新申请.");
                    orderDeclarationDAO.save(odTemp);
                }

                System.out.println(flag);
                in.close();
                return true;
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }

        return false;
    }
}
